package com.ali8ba.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ali8ba.common.PageInfo;

/**
 * 通用泛型Dao实现
 * 
 * @Repository("jpaDao")
 * @author xiamu
 * @Repository
 * @param <T>
 * @param <ID>
 */

public class JpaDao<T, ID extends Serializable> implements IGenericDao<T, ID> {

	@PersistenceContext
	protected EntityManager em;

	private Class<T> clazz;

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	public Class<T> getClazz() {
		return clazz;
	}

	public void setClazz(Class<T> clazz) {
		this.clazz = clazz;
	}

	public JpaDao() {

		this.clazz = (Class<T>) ((ParameterizedType) this.getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];

	}

	public T find(Class<T> clazz, ID id) {

		return em.getReference(clazz, id);
	}


	private Query createQuery(String jpql) {

		return null;
	}

	@Override
	public void delete(T t) {

		em.remove(t);
	}

	public JpaDao(Class<T> clazz) {

		this.clazz = clazz;

	}

	public T get(Serializable id) {

		if (id == null)

			return null;

		return (T) em.find(clazz, id);

	}

	public List<T> find(String jpql) {
          //  em.createQuery("").getSingleResult()
		return em.createQuery(jpql).getResultList();

	}
	


	@Override
	public T findForObject(String jpql,Object... params) {
		
		 List<T> list=this.find(jpql, params);
		 if(list.size()>0){
			 return (T) list.get(0);
		 }
		return null;
	}
	
	

	@Override
	public T findForObject(String jpql, Object param) {
		
		 List<T> list=this.find(jpql, param);
		 if(list.size()>0){
			 return (T)list.get(0);
		 }
		return null;
	}

	@SuppressWarnings("unchecked")
	public List<T> find(String jpql, Object param) {

		Query query = em.createQuery(jpql);

		setParameter(query, param);

		return query.getResultList();
	}

	private void setParameter(Query query, Object param) {
		if (param != null) {
			query.setParameter(1, param);
		}
	}

	private void setParameters(Query query, Object... params) {
		int i;
		if (params != null) {
			for (i = 0; i < params.length; ++i) {
				query.setParameter(i + 1, params[i]);
			}

		}
	}

	public List<T> find(String jpql, Object... params) {

		Query query = em.createQuery(jpql);
		setParameters(query, params);

		return query.getResultList();

	}

	@Override
	public List<T> findWithSize(String jpql, int size, Object... params) {

		Query query = em.createQuery(jpql);

		setParameters(query, params);

		query.setMaxResults(size);

		return query.getResultList();
	}

	@Override
	public PageInfo<T> findForPage(String jpql, int index, int pageSize,
			Object... params) {

		Query query = em.createQuery(jpql);

		setParameters(query, params);

		query.setFirstResult(0);

		query.setMaxResults(pageSize);

		List<T> list = query.getResultList();
		
		

		return null;
	}

	public long getSingleResult(String jpql) {

		Object obj = em.createQuery(jpql).getSingleResult();

		if (obj == null) {

			return 0;
		} else {
			return (Long) obj;

		}

	}

	@Override
	public long getSingleResult(String jpql, Object... params) {

		Query query = em.createQuery(jpql);

		setParameters(query, params);

		Object obj = query.getSingleResult();

		if (obj == null) {

			return 0;
		} else {
			return (Long) obj;

		}
	}

	public void save(Object t) {

		em.persist(t);

	}

	public T saveOrUpdate(Object t) {
	
		return (T) em.merge(t);

	}

	@Override
	public long batchUpdate(String jpal) {

		Query query = em.createQuery(jpal);

		return query.executeUpdate();

	}
	
	

//	@Override
//	public List findByNativeSQL(String jpql, Object... params) {
//		
//		Query query = em.createNativeQuery(jpql);
//
//		setParameters(query, params);
//
//		return query.getResultList();
//	}

	public void setEm(EntityManager em) {
		this.em = em;
	}

	public List<T> getNewRndIds(int num) {
		String hql = "select role from " + this.clazz.getName() + " role where role.userId is null order by rand() ";
		
		List<T> tList= this.findWithSize(hql, num);
		
		return tList;
	}
	

}
